#pragma once

template<typename Ty>
class hListNode
{
	template<typename Ty, typename Alloc>
	friend class hList;
	template<typename Ty>
	friend class hListIterator;
	template<typename Ty>
	friend class hListConstIterator;
	template <typename, typename, bool>
	friend struct _hIntervalMapIterator;

	Ty* _data = NULL;
	hListNode<Ty>* _other[2] = {};
public:
	hListNode<Ty>*& next(bool rFlag) { return _other[rFlag ? 0 : 1]; }
	hListNode<Ty>* const& next(bool rFlag) const { return _other[rFlag ? 0 : 1]; }
	hListNode<Ty>*& prev(bool rFlag) { return _other[rFlag ? 1 : 0]; }
	hListNode<Ty>* const& prev(bool rFlag) const { return _other[rFlag ? 1 : 0]; }
};

template<typename Ty>
class hListIterator
{
	template<typename Ty, typename Alloc>
	friend class hList;

	bool _rvFlag = false;
	hListNode<Ty>* _node = NULL;
public:
	hListIterator() {}
	hListIterator(hListNode<Ty>* pNode) { _node = pNode; }
	hListNode<Ty>* getRaw() { return _node; }

	Ty& operator*();
	hListIterator& operator++();
	hListIterator operator++(int);
	bool operator==(const hListIterator& other) const;
	bool operator!=(const hListIterator& other) const { return !(*this == other); }
};

template<typename Ty>
class hListConstIterator
{
	template<typename Ty, typename Alloc>
	friend class hList;

	bool _rvFlag = false;
	const hListNode<Ty>* _node = NULL;
public:
	const Ty& operator*();
	hListConstIterator& operator++();
	hListConstIterator operator++(int);
	bool operator==(const hListConstIterator& other);
	bool operator!=(const hListConstIterator& other) { return !(*this == other); }
};

template<typename Ty, typename Alloc>
inline hList<Ty, Alloc>::hList()
{
	_node._other[0] = &_node;
	_node._other[1] = &_node;
}

template<typename Ty, typename Alloc>
hList<Ty, Alloc>::~hList()
{
}

template<typename Ty, typename Alloc>
hList<Ty, Alloc>::Iter hList<Ty, Alloc>::erase(Iter it)
{
	assert(&_node != it._node);
	assert(_num);

	--_num;
	it._node->next(_rvFlag)->prev(_rvFlag) = it._node->prev(_rvFlag);
	it._node->prev(_rvFlag)->next(_rvFlag) = it._node->next(_rvFlag);

	return Iter(it._node->next(_rvFlag));
}

template<typename Ty, typename Alloc>
void hList<Ty, Alloc>::clear()
{
	_node._other[0] = &_node;
	_node._other[1] = &_node;
	_num = 0;
}

template<typename Ty, typename Alloc>
typename hList<Ty, Alloc>::Iter hList<Ty, Alloc>::begin()
{
	Iter it;
	it._rvFlag = _rvFlag;
	it._node = _node.next(_rvFlag);
	return it;
}

template<typename Ty, typename Alloc>
typename hList<Ty, Alloc>::CIter hList<Ty, Alloc>::begin() const
{
	CIter it;
	it._rvFlag = _rvFlag;
	it._node = _node.next(_rvFlag);
	return it;
}

template<typename Ty, typename Alloc>
typename hList<Ty, Alloc>::Iter hList<Ty, Alloc>::end()
{
	Iter it;
	it._node = &_node;
	return it;
}

template<typename Ty, typename Alloc>
typename hList<Ty, Alloc>::CIter hList<Ty, Alloc>::end() const
{
	CIter it;
	it._node = &_node;
	return it;
}

template<typename Ty, typename Alloc>
template <class... Arg>
std::pair<typename hList<Ty, Alloc>::Iter, bool> hList<Ty, Alloc>::emplaceBack(Arg&&... param)
{
	_Node* pNode = _AllocNode::alloc();
	if (!pNode)
		return std::make_pair(end(), false);

	_AllocNode::create(pNode);
	pNode->_data = _AllocTy::alloc();
	if (!pNode->_data)
	{
		_AllocNode::destroy(pNode);
		_AllocNode::dealloc(pNode);
		return std::make_pair(end(), false);
	}
	_AllocTy::create(pNode->_data, std::forward<Arg>(param)...);

	++_num;
	pNode->prev(_rvFlag) = _node.prev(_rvFlag);
	pNode->next(_rvFlag) = &_node;
	_node.prev(_rvFlag)->next(_rvFlag) = pNode;
	_node.prev(_rvFlag) = pNode;

	Iter it;
	it._rvFlag = _rvFlag;
	it._node = pNode;
	return std::make_pair(it, true);
}

template<typename Ty>
Ty& hListIterator<Ty>::operator*()
{
	assert(_node);
	assert(_node->_data);
	return *_node->_data;
}

template<typename Ty>
hListIterator<Ty>& hListIterator<Ty>::operator++()
{
	assert(_node);
	assert(_node->_data);
	_node = _node->next(_rvFlag);
	return *this;
}

template<typename Ty>
hListIterator<Ty> hListIterator<Ty>::operator++(int)
{
	assert(_node);
	assert(_node->_data);
	hListIterator<Ty> it;
	it._rvFlag = _rvFlag;
	it._node = _node;
	_node = _node->next(_rvFlag);
	return it;
}

template<typename Ty>
bool hListIterator<Ty>::operator==(const hListIterator<Ty>& other) const
{
	return _node == other._node;
}

template<typename Ty>
const Ty& hListConstIterator<Ty>::operator*()
{
	assert(_node);
	assert(_node->_data);
	return *_node->_data;
}

template<typename Ty>
hListConstIterator<Ty>& hListConstIterator<Ty>::operator++()
{
	assert(_node);
	assert(_node->_data);
	_node = _node->next(_rvFlag);
	return *this;
}

template<typename Ty>
hListConstIterator<Ty> hListConstIterator<Ty>::operator++(int)
{
	assert(_node);
	assert(_node->_data);
	hListConstIterator<Ty> it;
	it._rvFlag = _rvFlag;
	it._node = _node;
	_node = _node->next(_rvFlag);
	return it;
}

template<typename Ty>
bool hListConstIterator<Ty>::operator==(const hListConstIterator<Ty>& other)
{
	return _node == other._node;
}

